use cmsis_rtos2_rs::os_delay;
use driver_utils::ic::ads1115::convert_temp_ntc_10k;
use driver_utils::ic::ads1115::Ads1115;
use driver_utils::ic::ads1115::Channel;
use driver_utils::interface::soft_i2c::SI2c;
use driver_utils::interface::soft_i2c::SoftI2c;
use driver_utils::interface::DelayMs;
use periph_utils::cortex_m::asm;
use periph_utils::GpioConfig;
use periph_utils::stm32f1;
use crate::cp_heat::HeatErr;


#[derive(GpioConfig, Debug)]
#[gpio(init = "gpio_init",
    io(name = "sda", io = "PB7", mode = "OUT_OD", set, reset, read, level),
    io(name = "scl", io = "PB8", mode = "OUT_OD", set, reset, level),
    io(name = "rdy", io = "PB6", mode = "IN_FLOAT", read),
)]
struct Init;

pub unsafe fn init() {
    Init::gpio_init();
}

#[derive(Default, Debug, Clone, Copy)]
pub struct Temp {
    pub water: i16,
    pub steam: i16,
}

pub fn read() -> Result<Temp, HeatErr> {
    type I2C = SI2c<Init>;
    let i2c = I2C::const_new();
    let mut adc: Ads1115<I2C, Init> = Ads1115::new(i2c);
    let water = adc.read_single_shot(Channel::A0A1).map_err(|_| HeatErr::Temp)?;
    let steam = adc.read_single_shot(Channel::A2A3).map_err(|_| HeatErr::Temp)?;

    let water = convert_temp_ntc_10k(water).ok_or(HeatErr::Temp)?;
    let steam = convert_temp_ntc_10k(steam).ok_or(HeatErr::Temp)?;

    Ok(Temp { water, steam })
}


impl DelayMs for Init {

    #[inline(always)]
    fn delay_ms(ms: u32) {
        os_delay(ms);
    }
}

impl SoftI2c for Init {
    fn delay() {
        asm::delay(10);
    }

    #[inline(always)]
    fn read_sda() -> bool {
        Init::sda_read()
    }   
    
    #[inline(always)]
    fn reset_scl() {
        Init::scl_reset();
    }

    #[inline(always)]
    fn reset_sda() {
        Init::sda_reset();
    }

    #[inline(always)]
    fn set_scl() {
        Init::scl_set();
    }

    #[inline(always)]
    fn set_sda() {
        Init::sda_set();
    }
}


